package com.sjh.lib_app.utils

import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Build
import android.text.InputFilter
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.EditText
import androidx.annotation.ColorRes
import androidx.annotation.DimenRes
import androidx.annotation.LayoutRes
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import androidx.databinding.ViewDataBinding
import com.blankj.utilcode.constant.PermissionConstants
import com.blankj.utilcode.util.ActivityUtils
import com.blankj.utilcode.util.PermissionUtils
import com.luck.picture.lib.entity.LocalMedia
import com.sjh.lib_app.adapter.BaseBinder
import com.sjh.baseutils.println
import com.sjh.baseutils.toast
import me.drakeet.multitype.MultiTypeAdapter
import java.math.RoundingMode
import java.text.DecimalFormat
import java.util.regex.Matcher
import java.util.regex.Pattern


/**
 * 一些扩展方法
 * @author Extends
 * @date 2020/6/12
 */

/**
 * 通过LayoutId便捷获取ViewDataBinding的方法
 * 主要还是为了在 Fragment 里面写R.layout.xxxxxx,方便点击跳转
 */
fun <T : ViewDataBinding> androidx.fragment.app.Fragment.getDataBinding(@LayoutRes id: Int,
                                                                        parent: ViewGroup? = null,
                                                                        attachToParent: Boolean = parent != null): T {
    val binding = DataBindingUtil.inflate<T>(LayoutInflater.from(context), id, parent, attachToParent)
    binding.lifecycleOwner = this
    return binding
}

/**
 * 通过LayoutId便捷获取ViewDataBinding的方法
 * 主要还是为了在 Activity 里面写R.layout.xxxxxx,方便点击跳转
 */
fun <T : ViewDataBinding> AppCompatActivity.getDataBinding(@LayoutRes id: Int,
                                                           parent: ViewGroup? = null,
                                                           attachToParent: Boolean = parent != null): T {
    val binding = DataBindingUtil.inflate<T>(layoutInflater, id, parent, attachToParent)
    binding.lifecycleOwner = this
    return binding
}

/**
 * 检查权限
 * @param per 需要检查的权限
 * @param permissionName 显示在对话框中的 权限中文名称
 * @param granted 同意权限后的操作
 */
fun checkPermission(@PermissionConstants.Permission per: Array<String>,
                    permissionName: String = "",
                    isLooper: Boolean = false,
                    onDenied: (() -> Unit)? = null,
                    granted: () -> Unit) {
    PermissionUtils.permission(*per)
        .rationale { activity, shouldRequest -> PermissionDialogHelper.showRationaleDialog(shouldRequest, permissionName) }
        .callback(object : PermissionUtils.FullCallback {
            override fun onGranted(granted: MutableList<String>) {
                //同意权限
                "同意权限".println()
                granted()
            }

            override fun onDenied(deniedForever: MutableList<String>, denied: MutableList<String>) {
                "拒绝了权限".println()
                PermissionDialogHelper.showOpenAppSettingDialog(permissionName) {
                    if (onDenied != null) {
                        onDenied()
                    } else {
                        if (isLooper) {
                            checkPermission(per, permissionName, isLooper, null, granted)
                        }
                    }

                }
            }
        }).request()
}

//returns dip(dp) dimension value in pixels
@Deprecated("调用 com.yzjt.baseutils DelegatesExtensions  Number.dp")
fun Context.dip(value: Int): Int = (value * resources.displayMetrics.density).toInt()

@Deprecated("调用 com.yzjt.baseutils DelegatesExtensions  Number.dp")
fun Context.dip(value: Float): Int = (value * resources.displayMetrics.density).toInt()

//return sp dimension value in pixels
fun Context.sp(value: Int): Int = (value * resources.displayMetrics.scaledDensity).toInt()
fun Context.sp(value: Float): Int = (value * resources.displayMetrics.scaledDensity).toInt()

//converts px value into dip or sp
fun Context.px2dip(px: Int): Float = px.toFloat() / resources.displayMetrics.density
fun Context.px2sp(px: Int): Float = px.toFloat() / resources.displayMetrics.scaledDensity

fun Context.dimen(@DimenRes resource: Int): Int = resources.getDimensionPixelSize(resource)


//the same for the views
@Deprecated("调用 com.yzjt.baseutils DelegatesExtensions  Number.dp")
inline fun View.dip(value: Int): Int = context.dip(value)

@Deprecated("调用 com.yzjt.baseutils DelegatesExtensions  Number.dp")
inline fun View.dip(value: Float): Int = context.dip(value)
inline fun View.sp(value: Int): Int = context.sp(value)
inline fun View.sp(value: Float): Int = context.sp(value)
inline fun View.px2dip(px: Int): Float = context.px2dip(px)
inline fun View.px2sp(px: Int): Float = context.px2sp(px)
inline fun View.dimen(@DimenRes resource: Int): Int = context.dimen(resource)

/**
 * 返回颜色
 */
fun Context.color(@ColorRes id: Int): Int {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        return resources.getColor(id, null)
    }
    return resources.getColor(id)
}

/**
 * 打开qq和指定的qq联系
 * 注：指定qq好像只能是开通了客服功能的QQ号
 */
fun contactFromQq(qq: String?) {
    if (qq.isNullOrBlank()) {
        "客服忙，请稍后再试".toast()
        return
    }
    try {
        val url = "mqqwpa://im/chat?chat_type=wpa&uin=$qq" //uin是发送过去的qq号码
        ActivityUtils.getTopActivity().startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(url)))
    } catch (e: Exception) {
        e.printStackTrace()
        "您的手机还没有安装QQ".toast()
    }
}

/**
 * 直接拨打电话
 */
fun contactFromMobile(phoneNumber: String?) {
    if (phoneNumber.isNullOrBlank()) {
        "客服忙，请稍后再试".toast()
        return
    }
    try {
        val intent = Intent(Intent.ACTION_VIEW, Uri.parse("tel:$phoneNumber"))
        ActivityUtils.getTopActivity().startActivity(intent)
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

/**
 * 配合multitype使用的快速注册多种类型的item
 */
inline fun <reified T, V : ViewDataBinding> MultiTypeAdapter.register(@LayoutRes layoutId: Int): BaseBinder<T, V> {
    val binder = BaseBinder<T, V>(layoutId)
    register(T::class.java, binder)
    return binder
}


/**
 * 格式化 数据
 * @param xxxx万   xxxx亿
 */
fun String.formatNumber(): String {
    var number = this.replace(",", "").toDouble()
    if (number < 10000) {
        return number.toString()
    } else if (10000 <= number && number < 100000000) {
        val d = number / 10000
        return d.getNoMoreThanTwoDigits() + "万"
    } else if (number >= 100000000) {
        val d = number / 100000000
        return d.getNoMoreThanTwoDigits() + "亿"
    }
    return ""
}

/**
 * 格式化 数据
 * @param xxxx万   xxxx亿
 */
fun String.formatNumber2(): String {
    if (this.toInt() < 10000) {
        return this
    }
    var number = this.replace(",", "").toDouble()
    if (10000 <= number && number < 100000000) {
        val d = number / 10000
        return d.getNoMoreThanTwoDigits() + "万"
    } else if (number >= 100000000) {
        val d = number / 100000000
        return d.getNoMoreThanTwoDigits() + "亿"
    }
    return ""
}

/**
 * 对入参保留最多两位小数(舍弃末尾的0)，如:
 * 3.345->3.34
 * 3.40->3.4
 * 3.0->3
 */
fun Double.getNoMoreThanTwoDigits(): String {
    val format = DecimalFormat("0.##")
    //未保留小数的舍弃规则，RoundingMode.FLOOR表示直接舍弃。
    format.roundingMode = RoundingMode.FLOOR
    return format.format(this)
}

/**
 * 限制EdtiView特殊字符 包括 空格输入
 */
fun EditText.setEditTextInhibitInputSpaChat(maxLength: Int = Int.MAX_VALUE) {
    val filter_space = InputFilter { source, start, end, dest, dstart, dend -> if (source == " ") "" else null }

    val filter_speChat = InputFilter { charSequence, i, i1, spanned, i2, i3 ->
        val speChat = "[`~!@#_$%^&*()+=|{}':;',\\[\\].<>/?~！@#￥%……&*（）— +|{}【】‘；：”“’。，、？]"
        val pattern: Pattern = Pattern.compile(speChat)
        val matcher: Matcher = pattern.matcher(charSequence.toString())
        if (matcher.find()) "" else null
    }
    this.filters = arrayOf(filter_space, filter_speChat, InputFilter.LengthFilter(maxLength))
}
/**
 * 获取最佳的图片
 */
fun LocalMedia.getExtendsionPath() = when {
    isOriginal -> originalPath
    isCompressed -> compressPath
    isCut -> cutPath
    Build.VERSION.SDK_INT >= 29 -> androidQToPath
    else -> path
}